#!/usr/bin/env python
# -*- coding:utf-8 -*-
from django.conf.urls import url
from django.utils.safestring import mark_safe
from django.shortcuts import HttpResponse, render
from django.http import JsonResponse
from stark.service.v1 import site, StarkHandler, get_choice_text
from django.urls import reverse
from web import models
from utils.exceptions import NotExistsCommentException

from utils.oschina import OsChina


class ClassListHandler(StarkHandler):

    def display_edit(self, obj=None, is_header=None, *args, **kwargs):
        if is_header:
            return '班级'
        title = "%s%s（%s）" % (obj.get_course_display(), obj.title, obj.get_school_display())
        return title

    def members(self, obj=None, is_header=None, *args, **kwargs):
        if is_header:
            return '成员仓库'
        record_url = reverse('stark:web_member_list', kwargs={'cls_id': obj.pk})
        return mark_safe('<a href="%s">查看(%s)</a>' % (record_url, obj.member_set.count()))

    def issues(self, obj=None, is_header=None, *args, **kwargs):
        if is_header:
            return 'issues'

        url_name = "%s:%s" % (self.site.namespace, self.get_url_name('issues'),)
        record_url = reverse(url_name, kwargs={'cls_id': obj.pk})
        return mark_safe('<a target="_blank" href="%s">issues</a>' % record_url)

    list_display = [display_edit, 'org', 'teach_repo', issues, members, ]

    def extra_urls(self):
        patterns = [
            url(r'^issues/(?P<cls_id>\d+)/$', self.wrapper(self.issues_view), name=self.get_url_name('issues')),
            url(r'^comments/$', self.wrapper(self.comments_view),
                name=self.get_url_name('comments')),
        ]
        return patterns

    def gen_table_list(self, class_object):
        """
        生成表格列表
        :return:
        """
        result = OsChina.load_issues(org=class_object.org, repo=class_object.teach_repo, labels='作业')
        if not result.status:
            return
        # 班级所有人
        member_list = class_object.member_set.all().values('username', 'real_name', 'nick_name')
        for index in range(len(result.data)):
            issue = result.data[index]
            info = {
                'number': issue['number'],
                'title': issue['title'],
                'html_url': issue['html_url'],
                'created_at': issue['created_at'],
                'rate': '-',
                'uncommitted_user': ''
            }
            if index != 0:
                yield info
                continue


            comments_response = OsChina.load_comments(org=class_object.org, repo=class_object.teach_repo,
                                                      number=issue['number'])
            
            if not comments_response.status:
                yield info
                continue

            committed_user_set = {item['user']['login'] for item in comments_response.data}
            uncommitted_user_list = [row['real_name'] or row['nick_name'] for row in member_list if
                                     row['username'] not in committed_user_set]
            info['uncommitted_user'] = ','.join(uncommitted_user_list)
            info['rate'] = "%s/%s" % (len(member_list) - len(uncommitted_user_list), len(member_list))
            yield info

    def issues_view(self, request, *args, **kwargs):
        """
        根据API获取教学计划中的所有issues。
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        cls_id = kwargs.get('cls_id')
        class_object = models.ClassList.objects.filter(id=cls_id).first()
        if not class_object:
            return HttpResponse('数据不存在')
        fetch_comment_url_name = "%s:%s" % (self.site.namespace, self.get_url_name('comments'),)
        return render(request,
                      'web/issues.html',
                      {
                          'body_list': self.gen_table_list(class_object),
                          'cls_id': cls_id,
                          'fetch_comment_url_name': fetch_comment_url_name
                      })

    def comments_view(self, request, *args, **kwargs):
        """
        获取评论信息
        :param request:
        :param cls_id:
        :param number:
        :return:
        """
        result = {'status': True, 'error': None, 'data': None}
        try:
            cls_id = request.GET.get('cls_id')
            class_object = models.ClassList.objects.filter(id=cls_id).first()
            if not class_object:
                return HttpResponse('请求错误')
            number = request.GET.get('number')
            comments_response = OsChina.load_comments(org=class_object.org,
                                                      repo=class_object.teach_repo, number=number)
            if not comments_response.status:
                raise NotExistsCommentException(comments_response.error)

            committed_user_set = {item['user']['login'] for item in comments_response.data}

            # 班级所有人
            member_list = class_object.member_set.all().values('username', 'real_name', 'nick_name')
            uncommitted_user_list = [row['real_name'] or row['nick_name'] for row in member_list if
                                     row['username'] not in committed_user_set]
            rate = "%s/%s" % (len(member_list) - len(uncommitted_user_list), len(member_list))
            result['data'] = {'uncommitted_user': ','.join(uncommitted_user_list), 'rate': rate}
        except NotExistsCommentException as e:
            result['status'] = False
            result['error'] = str(e)
        except Exception as e:
            result['status'] = False
            result['error'] = '请求异常'

        return JsonResponse(result)


site.register(models.ClassList, ClassListHandler)


class MemberHandler(StarkHandler):

    def display_repo_name(self, obj=None, is_header=None, *args, **kwargs):
        if is_header:
            return '仓库'
        repo_name = obj.repo_name.strip()
        if not repo_name:
            return ""
        result = []
        for item in repo_name.split(','):
            repo_url = "https://gitee.com/%s/%s" % (obj.cls.org, item,)
            result.append('<a target="_blank" href="%s">%s</a>' % (repo_url, item,))

        return mark_safe('</br>'.join(result))

    list_display = ['real_name', 'nick_name', 'username', display_repo_name, ]
    exclude_fields = ['cls', ]
    per_page_count = 100

    def display_edit_del(self, obj=None, is_header=None, *args, **kwargs):
        if is_header:
            return '操作'

        cls_id = kwargs.get('cls_id')

        if obj.repo_name:
            target = '_self'
            org_member_url = '#'
            text = '删成员(需先删库)'
        else:
            target = '_blank'
            org_member_url = 'https://gitee.com/organizations/%s/members' % (obj.cls.org,)
            text = '删除成员'
        tpl = '<a class="btn btn-default btn-xs" href="%s">编辑</a> <a target="%s" class="btn btn-danger btn-xs" href="%s">%s</a>' % (
            self.reverse_change_url(pk=obj.pk, cls_id=cls_id), target, org_member_url, text)
        return mark_safe(tpl)

    def get_urls(self):
        patterns = [
            url(r'^list/(?P<cls_id>\d+)/$', self.wrapper(self.changelist_view), name=self.get_list_url_name),
            url(r'^add/(?P<cls_id>\d+)/$', self.wrapper(self.add_view), name=self.get_add_url_name),
            url(r'^change/(?P<cls_id>\d+)/(?P<pk>\d+)/$', self.wrapper(self.change_view),
                name=self.get_change_url_name),
            url(r'^delete/(?P<cls_id>\d+)/(?P<pk>\d+)/$', self.wrapper(self.delete_view),
                name=self.get_delete_url_name),
        ]
        patterns.extend(self.extra_urls())
        return patterns

    def get_queryset(self, request, *args, **kwargs):
        cls_id = kwargs.get('cls_id')
        return super().get_queryset(request, *args, **kwargs).filter(cls_id=cls_id)

    def save(self, request, form, is_update, *args, **kwargs):
        cls_id = kwargs.get('cls_id')
        if not is_update:
            form.instance.cls_id = cls_id
        return form.instance.save()

    def action_load_member(self, request, *args, **kwargs):
        """
        自动加载成员，根据码云api自动读取所有成员和项目。
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        # 获取数据中已有的成员
        # 获取码云中已有的成员
        cls_id = kwargs.get('cls_id')
        class_object = models.ClassList.objects.filter(id=cls_id).first()
        if not class_object:
            return

        result = OsChina.load_project_members(org=class_object.org, role='member')
        remote_dict = result.data
        remote_user_set = set(remote_dict)

        db_member_list = models.Member.objects.filter(cls=class_object)
        db_user_set = set()
        db_member_dict = {}
        for item in db_member_list:
            db_user_set.add(item.username)
            db_member_dict[item.username] = item

        # 需要添加
        add_user_list = remote_user_set - db_user_set
        member_object_list = []
        for username in add_user_list:
            row_dict = remote_dict[username]
            row_object = models.Member(cls=class_object, username=username, real_name=row_dict.get('real_name', ''),
                                       nick_name=row_dict['nick_name'], repo_name=",".join(row_dict['repo_name']))
            member_object_list.append(row_object)
        models.Member.objects.bulk_create(member_object_list)
        # 需要删除
        delete_user_list = db_user_set - remote_user_set
        models.Member.objects.filter(cls=class_object, username__in=delete_user_list).delete()

        # 需要更新
        update_user_list = remote_user_set & db_user_set
        for username in update_user_list:
            db_row_object = db_member_dict[username]
            remote_repo_name = ','.join(remote_dict[username]['repo_name'])
            if db_row_object.repo_name != remote_repo_name:
                db_row_object.repo_name = remote_repo_name
                db_row_object.save()

    action_load_member.text = '同步成员仓库'

    action_list = [action_load_member, ]


site.register(models.Member, MemberHandler)
